package org.example.analysis.service;

import lombok.extern.slf4j.Slf4j;
import org.example.analysis.model.*;
import org.example.analysis.service.analyzer.MethodAnalyzer;
import org.example.analysis.service.dataobj.ClassDataObject;
import org.example.analysis.service.dataobj.MethodDataObject;

import java.util.*;
import java.util.regex.Pattern;

/**
 * 方法复杂度分析器
 */
@Slf4j
public class MethodComplexityAnalyzer {
    // 用于缓存已分析过的方法复杂度
    private final Map<String, MethodComplexity> complexityCache = new HashMap<>();
    // 用于检测循环调用
    private final Set<String> methodCallStack = new HashSet<>();
    // 当前正在分析的项目名称
    private String currentProjectName;
    // 代码分析服务
    private final CodeAnalysisDbService codeAnalysisService;
    private final MethodAnalyzer methodAnalyzer = new MethodAnalyzer();

    public MethodComplexityAnalyzer() {
        this.codeAnalysisService = new CodeAnalysisDbService();
    }
    
    public void setCurrentProjectName(String projectName) {
        this.currentProjectName = projectName;
    }
    
    // 条件语句的正则表达式
    private static final Pattern CONDITION_PATTERN = Pattern.compile(
            "\\b(if|else|for|while|do|switch|case|catch|\\?|\\|\\||&&)\\b");
    
    // SQL操作的正则表达式
    private static final Pattern SQL_PATTERN = Pattern.compile(
            "\\b(select|insert|update|delete|merge|create|alter|drop)\\b", 
            Pattern.CASE_INSENSITIVE);
    
    /**
     * 分析方法复杂度
     */
    public MethodComplexity analyze(List<ClassDataObject> allClasses, MethodDataObject methodInfo, ClassDataObject classInfo) {
        if (methodInfo == null) return null;
        if(Objects.nonNull(methodInfo.getMethodComplexity())){
            return methodInfo.getMethodComplexity();
        }
        // 生成方法的唯一标识
        String methodKey = generateMethodKey(classInfo,methodInfo);
        log.info("正在分析方法: {}", methodInfo.getMethodName());
        // 如果已经分析过，直接返回缓存结果
        if (complexityCache.containsKey(methodKey)) {
            return complexityCache.get(methodKey);
        }
        
        // 检测循环调用
        if (methodCallStack.contains(methodKey)) {
            log.warn("检测到方法循环调用: {}", methodKey);
            return null;
        }
        
        try {
            // 将当前方法加入调用栈
            methodCallStack.add(methodKey);
            // 创建复杂度对象
            MethodComplexity complexity = new MethodComplexity();
           // complexity.setProjectName(methodInfo.getProjectName());
            complexity.setClassName(classInfo.getClassName());
            complexity.setMethodName(methodInfo.getMethodName());
            
            // 1. 基本指标
            complexity.setLinesOfCode(calculateLinesOfCode(methodInfo));
            complexity.setParameterCount(methodInfo.getParameters().size());
            
            // 2. 圈复杂度（条件分支数）
            int cyclomaticComplexity = calculateCyclomaticComplexity(methodInfo);
            complexity.setCyclomaticComplexity(cyclomaticComplexity);
            
            // 3. 局部变量数量
            complexity.setLocalVariableCount(calculateLocalVariableCount(methodInfo));

            // 4. 方法调用数量和递归分析
            complexity.setMethodCallCount(methodInfo.getCalledMethods().size());
            complexity.setNestingDepth(calculateNestingDepth(methodInfo));
            complexity.setExceptionHandlerCount(calculateExceptionHandlerCount(methodInfo));
            complexity.setSqlOperationCount(calculateSqlOperationCount(methodInfo));
            // 计算复杂度等级
            complexity.setLevel(calculateComplexityLevel(complexity));
            // 缓存分析结果
            complexityCache.put(methodKey, complexity);
            methodInfo.setMethodComplexity(complexity);
            methodInfo.setComplexityScore(complexity.getComplexityScore());
            return complexity;
        } finally {
            // 移除当前方法的调用栈记录
            methodCallStack.remove(methodKey);
        }
    }

    
    /**
     * 判断是否是项目内的方法
     */
    private boolean isProjectMethod(MethodDataObject methodInfo) {
//        if (methodInfo == null || methodInfo.getProjectName() == null) {
//            return false;
//        }
//        return methodInfo.getProjectName().equals(currentProjectName);
        return true;
    }
    
    /**
     * 生成方法的唯一标识
     */
    private String generateMethodKey(ClassDataObject classInfo,MethodDataObject methodInfo) {
        return String.format("%s.%s.%s.%s",
            classInfo.getPackageName(),
            classInfo.getClassName(),
            methodInfo.getMethodName(),
            methodInfo.getParametersKey());
    }
    
    /**
     * 计算代码行数
     */
    private int calculateLinesOfCode(MethodDataObject methodInfo) {
        return methodInfo.getCodeLines();
    }
    
    /**
     * 计算圈复杂度（条件分支数）
     */
    private int calculateCyclomaticComplexity(MethodDataObject methodInfo) {
        String methodBody = methodInfo.getMethodBody();
        if (methodBody == null) {
            return 1;
        }
        
        // 基础复杂度为1
        int complexity = 1;
        
        // 匹配所有条件语句
        var matcher = CONDITION_PATTERN.matcher(methodBody);
        while (matcher.find()) {
            complexity++;
        }
        
        return complexity;
    }
    
    /**
     * 计算局部变量数量
     */
    private int calculateLocalVariableCount(MethodDataObject methodInfo) {
        String methodBody = methodInfo.getMethodBody();
        if (methodBody == null) {
            return 0;
        }
        
        // 简单统计变量声明（这是一个简化的实现，实际应该使用AST分析）
        int count = 0;
        String[] lines = methodBody.split("\n");
        for (String line : lines) {
            line = line.trim();
            // 检查是否是变量声明
            if (line.matches("^\\s*(final\\s+)?(var|[\\w.<>]+)\\s+\\w+\\s*(=|;).*")) {
                count++;
            }
        }
        
        return count;
    }
    
    /**
     * 计算方法调用数量
     */
    private int calculateMethodCallCount(MethodDataObject methodInfo) {
        String methodBody = methodInfo.getMethodBody();
        if (methodBody == null) {
            return 0;
        }
        
        // 统计方法调用（这是一个简化的实现，实际应该使用AST分析）
        int count = 0;
        String[] lines = methodBody.split("\n");
        for (String line : lines) {
            line = line.trim();
            // 检查是否包含方法调用
            if (line.matches(".*\\w+\\s*\\(.*\\).*")) {
                count++;
            }
        }
        
        return count;
    }
    
    /**
     * 计算嵌套深度
     */
    private int calculateNestingDepth(MethodDataObject methodInfo) {
        String methodBody = methodInfo.getMethodBody();
        if (methodBody == null) {
            return 0;
        }
        
        int maxDepth = 0;
        int currentDepth = 0;
        
        // 统计花括号的嵌套深度
        for (char c : methodBody.toCharArray()) {
            if (c == '{') {
                currentDepth++;
                maxDepth = Math.max(maxDepth, currentDepth);
            } else if (c == '}') {
                currentDepth--;
            }
        }
        
        return maxDepth;
    }
    
    /**
     * 计算异常处理数量
     */
    private int calculateExceptionHandlerCount(MethodDataObject methodInfo) {
        String methodBody = methodInfo.getMethodBody();
        if (methodBody == null) {
            return 0;
        }
        
        int count = 0;
        String[] lines = methodBody.split("\n");
        for (String line : lines) {
            line = line.trim();
            // 检查try和catch块
            if (line.startsWith("try") || line.startsWith("catch")) {
                count++;
            }
        }
        
        return count;
    }
    
    /**
     * 计算SQL操作数量
     */
    private int calculateSqlOperationCount(MethodDataObject methodInfo) {
        String methodBody = methodInfo.getMethodBody();
        if (methodBody == null) {
            return 0;
        }
        
        int count = 0;
        var matcher = SQL_PATTERN.matcher(methodBody);
        while (matcher.find()) {
            count++;
        }
        
        return count;
    }
    
    /**
     * 计算复杂度等级
     * @param complexity 复杂度信息
     * @return 复杂度等级
     */
    private ComplexityLevel calculateComplexityLevel(MethodComplexity complexity) {
        // 计算复杂度得分
        int score = calculateComplexityScore(complexity);
        
        // 根据得分确定复杂度等级
        if (score >= 12) return ComplexityLevel.VERY_HIGH;
        if (score >= 8) return ComplexityLevel.HIGH;
        if (score >= 4) return ComplexityLevel.MEDIUM;
        return ComplexityLevel.LOW;
    }
    
    /**
     * 计算复杂度得分
     * @param complexity 复杂度信息
     * @return 复杂度得分
     */
    public int calculateComplexityScore(MethodComplexity complexity) {
        int score = 0;
        
        // 代码行数评分
        if (complexity.getLinesOfCode() > 200) score += 4;
        else if (complexity.getLinesOfCode() > 100) score += 3;
        else if (complexity.getLinesOfCode() > 50) score += 2;
        else if (complexity.getLinesOfCode() > 30) score += 1;
        
        // 圈复杂度评分
        if (complexity.getCyclomaticComplexity() > 15) score += 4;
        else if (complexity.getCyclomaticComplexity() > 10) score += 3;
        else if (complexity.getCyclomaticComplexity() > 5) score += 2;
        else if (complexity.getCyclomaticComplexity() > 3) score += 1;
        
        // 参数数量评分
        if (complexity.getParameterCount() > 6) score += 3;
        else if (complexity.getParameterCount() > 4) score += 2;
        else if (complexity.getParameterCount() > 2) score += 1;
        
        // 局部变量数量评分
        if (complexity.getLocalVariableCount() > 15) score += 3;
        else if (complexity.getLocalVariableCount() > 10) score += 2;
        else if (complexity.getLocalVariableCount() > 5) score += 1;
        
        // 方法调用数量评分
        if (complexity.getMethodCallCount() > 20) score += 3;
        else if (complexity.getMethodCallCount() > 10) score += 2;
        else if (complexity.getMethodCallCount() > 5) score += 1;
        
        // 嵌套深度评分
        if (complexity.getNestingDepth() > 5) score += 4;
        else if (complexity.getNestingDepth() > 3) score += 2;
        else if (complexity.getNestingDepth() > 2) score += 1;
        
        // 异常处理数量评分
        if (complexity.getExceptionHandlerCount() > 5) score += 3;
        else if (complexity.getExceptionHandlerCount() > 3) score += 2;
        else if (complexity.getExceptionHandlerCount() > 1) score += 1;
        
        // SQL操作数量评分
        if (complexity.getSqlOperationCount() > 5) score += 3;
        else if (complexity.getSqlOperationCount() > 3) score += 2;
        else if (complexity.getSqlOperationCount() > 1) score += 1;
        
        return score;
    }
} 